Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Always use main thread WebGPU for canvas initialization to fix macOS playback and ensure consistent NV12 frame handling.
macOS playback was broken because the canvas was transferred to a worker, and WebGPU in the worker context was failing to render NV12 frames correctly after recent Windows optimizations. By forcing all platforms to use the
initDirectCanvaspath, we leverage the existing main thread WebGPU renderer which correctly handles NV12 frames and has a robust canvas2d fallback. Theframe-worker.tschange adds a specific canvas2d fallback for queued WebGPU frames in the worker if WebGPU isn't initialized, ensuring robustness.Greptile Summary
frame-worker.tsto handle WebGPU frames when WebGPU renderer is unavailable, including NV12 to RGBA conversion and stride correctionImportant Files Changed
apps/desktop/src/routes/editor/Player.tsxapps/desktop/src/utils/frame-worker.tsapps/desktop/src-tauri/src/frame_ws.rsConfidence score: 4/5
crates/rendering/src/decoder/mod.rsandcrates/editor/src/playback.rsas the reduced timeouts and buffer sizes may impact performanceSequence Diagram
sequenceDiagram participant User participant Player as Player.tsx participant EditorInstance participant Playback participant SegmentMedia participant Decoder as VideoDecoder participant Renderer participant WebSocketServer as frame_ws.rs participant FrameWorker as frame-worker.ts User->>Player: "Click play button" Player->>EditorInstance: "startPlayback(fps, resolution)" EditorInstance->>Playback: "start(fps, resolution)" Playback->>Playback: "Initialize frame cache and prefetch buffer" loop "Video playback loop" Playback->>SegmentMedia: "get_frames(segment_time, !hide_camera, clip_offsets)" SegmentMedia->>Decoder: "get_frame(time)" Decoder->>Decoder: "Decode video frame from file" Decoder-->>SegmentMedia: "DecodedFrame" SegmentMedia-->>Playback: "DecodedSegmentFrames" Playback->>Renderer: "render_frame(segment_frames, uniforms, cursor)" Renderer->>Renderer: "Apply effects, camera overlay, cursor" Renderer-->>WebSocketServer: "RenderedFrame (via frame_cb)" WebSocketServer->>WebSocketServer: "Convert to NV12, downscale, pack metadata" WebSocketServer->>FrameWorker: "Send binary frame via WebSocket" FrameWorker->>FrameWorker: "Parse frame, queue for rendering" FrameWorker->>FrameWorker: "Render to canvas (WebGPU or Canvas2D)" FrameWorker-->>Player: "Display frame" Playback->>EditorInstance: "PlaybackEvent::Frame(frame_number)" EditorInstance-->>Player: "Update playhead position" end User->>Player: "Click pause/stop" Player->>EditorInstance: "stopPlayback()" EditorInstance->>Playback: "stop()" Playback->>Renderer: "Stop message"Context used:
dashboard- CLAUDE.md (source)dashboard- AGENTS.md (source)